package com.whut.monitor.util;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.whut.monitor.util.SystemUtil.getLocalMac;

/**
 * xml协议解析 第四版补偿器服务
 *
 * @author Sandeepin
 *         2017/11/9 0009
 */
public class XmlUtil {

    public static String xmlWriteCmds(String msg, Map<String, String> urlsMap, Map<String, String> cmdsMap) throws SocketException, UnknownHostException {
        // 构造头
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String time = dateFormat.format(new Date());
        String id = getLocalMac();
        if (msg == null){
            msg = "";
        }
        String preText = "<whut><head><time>" +
                time + "</time><id>" + id + "</id><msg>" +
                msg + "</msg></head><body>";

        // 构造urls cmds
        String urlsText = "";
        String cmdsText = "";
        if (urlsMap != null && urlsMap.size() > 0 ){
            String pre = "<urls>";
            StringBuilder temp = new StringBuilder();
            for (String akey : urlsMap.keySet()) {
                String[] t = akey.split(",");
                String s = "<" + t[0] + ">" +"<" + t[1] + ">" + urlsMap.get(akey)+ "</" + t[1] + ">" + "</" + t[0] + ">";
                temp.append(s);
            }
            String after = "</urls>";
            urlsText = pre + temp + after;
        }
        if (cmdsMap != null && cmdsMap.size() > 0 ){
            String pre = "<cmds>";
            StringBuilder temp = new StringBuilder();
            for (String akey : cmdsMap.keySet()) {
                String s = "<" + akey + ">" + cmdsMap.get(akey) + "</" + akey + ">";
                temp.append(s);
            }
            String after = "</cmds>";
            cmdsText = pre + temp + after;
        }

        // 结尾
        String afterText = "</body></whut>";
        return preText + urlsText + cmdsText + afterText;
    }

    /**
     * 读取xml文件到map
     *
     * @param xml 输入的xml文件字符串
     * @param map 输出map 键：xml的标签树 值：xml值
     * @return 是否解析成功
     * @throws DocumentException 异常
     */
    public static boolean xmlRead(String xml, Map<String, String> map) throws DocumentException {
        try {
            XmlReadCore xmlRead = new XmlReadCore(xml);
            Element root = xmlRead.getRootElement();
            xmlRead.getElementList(root);
            xmlRead.getMap(map);
        } catch (DocumentException e) {
            System.out.println(e.toString());
            return false;
        }
        return true;
    }

    /**
     * 第四版补偿器解析 读取xml文件到mapHead、mapData、mapCmds、mapUrls
     *
     * @param xml     输入的xml文件字符串
     * @param mapHead 头部数据
     * @param mapData 数值数据
     * @param mapCmds 指令数据
     * @param mapUrls 地址数据
     * @return 是否解析成功
     * @throws DocumentException 异常
     */
    public static boolean xmlRead(String xml, Map<String, String> mapHead, Map<String, String> mapData, Map<String, String> mapCmds, Map<String, String> mapUrls) throws DocumentException {
        Map<String, String> map = new TreeMap<String, String>();
        boolean bool = xmlRead(xml, map);
        for (String akey : map.keySet()) {
            if (akey.length() > 10) {
                if ("/whut/head/".equals(akey.substring(0, 11))) {
                    String key = akey.replace("/whut/head/", "");
                    mapHead.put(key, map.get(akey));
                }
                if (akey.length() > 15) {
                    if ("/whut/body/cmds/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/cmds/", "");
                        mapCmds.put(key, map.get(akey));
                    }
                    if ("/whut/body/urls/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/urls/", "");
                        mapUrls.put(key, map.get(akey));
                    }
                    if ("/whut/body/data/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/data/", "");
                        mapData.put(key, map.get(akey));
                    }
                }
            }
        }
        return bool;
    }

    /**
     * 第四版补偿器解析 兼容老的id风格（001-SDT00-00）
     *
     * @param xml     输入的xml文件字符串
     * @param mapHead 头部数据
     * @param mapData 数值数据
     * @param mapCmds 指令数据
     * @param mapUrls 地址数据
     * @return 是否解析成功
     * @throws DocumentException 异常
     */
    public static boolean xmlReadOld(String xml, Map<String, String> mapHead, Map<String, String> mapData, Map<String, String> mapCmds, Map<String, String> mapUrls) throws DocumentException {
        Map<String, String> map = new TreeMap<String, String>();
        boolean bool = xmlRead(xml, map);
        for (String akey : map.keySet()) {
            if (akey.length() > 10) {
                if ("/whut/head/".equals(akey.substring(0, 11))) {
                    String key = akey.replace("/whut/head/", "");
                    mapHead.put(key, map.get(akey));
                    if ("time".equals(key)) {
                        String value = map.get(akey);
                        value = value.substring(0, 4) +
                                "-" + value.substring(4, 6) +
                                "-" + value.substring(6, 8) +
                                " " + value.substring(8, 10) +
                                ":" + value.substring(10, 12) +
                                ":" + value.substring(12, 14);
                        mapHead.put(key, value);
                    }
                }
                if (akey.length() > 15) {
                    if ("/whut/body/cmds/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/cmds/", "");
                        key = key.replace("DEV", "");
                        mapCmds.put(key, map.get(akey));
                    }
                    if ("/whut/body/urls/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/urls/", "");
                        key = key.replace("DEV", "");
                        key = key.replace("/", "-");
                        mapUrls.put(key, map.get(akey));
                    }
                    if ("/whut/body/data/".equals(akey.substring(0, 16))) {
                        String key = akey.replace("/whut/body/data/", "");
                        key = key.replace("DEV", "");
                        key = key.replace("/", "-");
                        mapData.put(key, map.get(akey));
                    }
                }
            }
        }
        return bool;
    }

    public static class XmlReadCore {
        // 输入的字符串xml
        String srcXml;
        //存储xml元素信息的容器
        private List<Leaf> elemList = new ArrayList<Leaf>();

        XmlReadCore(String srcXml) {
            this.srcXml = srcXml;
        }

        /**
         * 获取根元素
         *
         * @return 根节点
         * @throws DocumentException 异常
         */
        Element getRootElement() throws DocumentException {
            Document srcdoc = DocumentHelper.parseText(srcXml);
            return srcdoc.getRootElement();
        }

        /**
         * 递归遍历方法
         *
         * @param element 元素
         */
        void getElementList(Element element) {
            List elements = element.elements();
            if (elements.size() == 0) {
                //没有子元素
                String xpath = element.getPath();
                String value = element.getTextTrim();
                elemList.add(new Leaf(xpath, value));
            } else {
                //有子元素
                for (Object element1 : elements) {
                    Element elem = (Element) element1;
                    //递归遍历
                    getElementList(elem);
                }
            }
        }

        String getListString() {
            StringBuilder sb = new StringBuilder();
            for (Leaf leaf : elemList) {
                sb.append(leaf.getXpath()).append(" = ").append(leaf.getValue()).append("\n");
            }
            return sb.toString();
        }

        void getMap(Map<String, String> outMap) {
            for (Leaf leaf : elemList) {
                outMap.put(leaf.getXpath(), leaf.getValue());
            }
        }

        /**
         * xml节点数据结构
         */
        class Leaf {
            private String xpath;
            private String value;

            public Leaf(String xpath, String value) {
                this.xpath = xpath;
                this.value = value;
            }

            public String getXpath() {
                return xpath;
            }

            public void setXpath(String xpath) {
                this.xpath = xpath;
            }

            public String getValue() {
                return value;
            }

            public void setValue(String value) {
                this.value = value;
            }
        }
    }

}
